﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BrightIdeasSoftware;
using ROrganizer.Client;
using ROrganizer.UI.Controllers;
using ROrganizer.UI.Forms.Core;

namespace ROrganizer.UI.Forms
{
    internal partial class ProposalManagerForm : Form
    {
        private readonly ProposalManagerFormController controller;
        private readonly GroupManager<ProposalManagerFormController.Proposal, object> groupper;

        public ProposalManagerForm()
        {
            this.controller = new ProposalManagerFormController(this.ProcessException);
            this.InitializeComponent();

            this.groupper = new GroupManager<ProposalManagerFormController.Proposal, object>(this.olvProposals, null);
            this.InitializeGroups();

            this.olvProposals.ShowGroups = true;
            this.olvProposals.AlwaysGroupByColumn = this.chAdded;
            this.olvProposals.Sort(this.chAdded, SortOrder.Descending);
            this.tsmiGroupByDate.Checked = true;

            this.olvProposals.UseFiltering = true;
            this.olvProposals.ModelFilter = this.controller;

            this.controller.Changed += this.OnChanged;
            this.controller.Proposals.CollectionChanged += this.OnChanged;
        }

        private void InitializeGroups()
        {
            this.groupper.Bind(this.tsmiGroupByTitle, this.chTitle, order: SortOrder.Ascending);
            this.groupper.Bind(this.tsmiGroupByUser, this.chUser, order: SortOrder.Ascending);
            this.groupper.Bind(this.tsmiGroupByHash, this.chHash, order: SortOrder.Ascending);
            this.groupper.Bind(this.tsmiGroupByDate, this.chAdded, order: SortOrder.Descending);

            this.groupper.SetKey(this.chAdded, x => x.Added.Date);
            this.groupper.SetFormat<DateTime>(this.chAdded, x => x.ToLongDateString());
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            e.Cancel = this.controller.IsWorking;
            base.OnClosing(e);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            this.olvProposals.Normalize();

            this.btnCancel.Enabled = this.controller.CanCancel();
            this.tsbRefresh.Enabled = this.controller.CanRefreshProposals();
            this.tsmiAccept.Enabled = this.controller.CanAcceptProposals(this.GetSelectedProposals());
            this.pbMain.Visible = this.controller.IsWorking;
        }

        private ProposalManagerFormController.Proposal[] GetSelectedProposals()
        {
            return this.olvProposals.SelectedObjects.OfType<ProposalManagerFormController.Proposal>().ToArray();
        }

        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);
            this.ExecuteAndWatch(this.controller.RefreshProposals, this);
        }

        private void OnChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Reset)
                this.olvProposals.ClearObjects();

            if (e.OldItems != null)
                this.olvProposals.RemoveObjects(e.OldItems);

            if (e.NewItems != null)
                this.olvProposals.AddObjects(e.NewItems);
        }

        private void OnChanged(object sender, EventArgs e)
        {
            if (this.SynchronizeInvocation(this.OnChanged, sender, e))
            {
                this.pbMain.Value = Math.Min(this.pbMain.Maximum, controller.Progress);
                this.btnCancel.Enabled = this.controller.CanCancel();
                this.tsbRefresh.Enabled = this.controller.CanRefreshProposals();
                this.tsmiAccept.Enabled = this.controller.CanAcceptProposals(this.GetSelectedProposals());
                this.pbMain.Visible = this.controller.IsWorking;

                if (!this.controller.IsWorking)
                    this.olvProposals.BuildList(true);
            }
        }

        private void OnCancel(object sender, EventArgs e)
        {
            this.ExecuteAndWatch(this.controller.Cancel);
        }

        private void OnRefresh(object sender, EventArgs e)
        {
            this.ExecuteAndWatch(this.controller.RefreshProposals, this);
        }

        private void OnAcceptProposal(object sender, EventArgs e)
        {
            this.ExecuteAndWatch(this.controller.AcceptProposals, this.GetSelectedProposals());
        }

        private void OnSelectionChanged(object sender, EventArgs e)
        {
            this.btnCancel.Enabled = this.controller.CanCancel();
            this.tsbRefresh.Enabled = this.controller.CanRefreshProposals();
            this.tsmiAccept.Enabled = this.controller.CanAcceptProposals(this.GetSelectedProposals());
        }
    }
}
